package com.gitee.feizns.jar;

import java.io.IOException;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author feizns
 * @since 2019/5/20
 */
public abstract class JarUtils {

    /**
     * 协议
     */
    public static final String PROTOCOL = "jar";


    /****************************************
     * 判断是否是jar资源
     ****************************************
     */
    public static final boolean isJar(String url) {
        return url.startsWith(PROTOCOL);
    }

    public static final boolean isJar(URL url) {
        return PROTOCOL.equals(url.getProtocol());
    }


    /****************************************
     * 获取jar文件
     ****************************************
     */
    public static final JarFile jarFile(String url) {
        try {
            return jarFile(new URL(url));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }

    public static final JarFile jarFile(URL url) {
        if ( isJar(url) ) {
            try {
                return ((JarURLConnection) url.openConnection()).getJarFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    public static final JarFile jarFile(Class<?> clz) {
        try {
            return jarFile(clz.getResource("").toURI().toURL());
        } catch (MalformedURLException | URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }


    /****************************************
     * 消费方式.
     ****************************************
     */
    public static final void consume(String url, Consumer<JarEntry> consumer) {
        consume(jarFile(url), consumer);
    }

    public static final void consume(URL url, Consumer<JarEntry> consumer) {
        try ( JarFile jarFile = jarFile(url) ) {
            consume(jarFile, consumer);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static final void consume(JarFile jarFile, Consumer<JarEntry> consumer) {
        consume(jarFile, item -> true, consumer);
    }


    /****************************************
     * 筛选消费.
     ****************************************
     */
    public static final void consume(JarFile jarFile, String prefix, Consumer<JarEntry> consumer) {
        consume(jarFile, item -> item.getName().startsWith(prefix), consumer);
    }

    public static final void consume(String url, String prefix, Consumer<JarEntry> consumer) {
        try ( JarFile jarFile = jarFile(url); ) {
            consume(jarFile, item -> item.getName().startsWith(prefix), consumer);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static final void consume(JarFile jarFile, Predicate<JarEntry> filter, Consumer<JarEntry> consumer) {
        Enumeration<JarEntry> entries = jarFile.entries();
        while ( entries.hasMoreElements() ) {
            JarEntry item = entries.nextElement();
            if ( filter.test(item) )
                consumer.accept(item);
        }
    }

    public static final void consume(Class<?> clz, Predicate<JarEntry> filter, Consumer<JarEntry> consumer) {
        try ( JarFile jarFile = jarFile(clz) ) {
            System.out.println(jarFile);
            consume(jarFile, filter, consumer);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
